package com.mall.wechat.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.mall.common.core.domain.entity.SysUser;
import com.mall.common.exception.ServiceException;
import com.mall.common.exception.base.BaseException;
import com.mall.common.utils.DateUtils;
import com.mall.common.utils.StringUtils;
import com.mall.common.utils.http.HttpUtils;
import com.mall.system.service.ISysUserService;
import com.mall.wechat.model.Vo.WxCodeVo;
import com.mall.wechat.model.Vo.WxLoginVo;
import com.mall.wechat.model.Vo.WxUserVo;
import com.mall.wechat.model.dto.WxLoginDto;
import com.mall.wechat.model.dto.WxUserDto;
import com.mall.wechat.service.IWeChatLoginService;
import com.mall.wechat.service.IWxUserService;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import sun.misc.BASE64Decoder;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.ArrayList;
import java.util.*;

@Service
public class WeChatLoginServiceImpl implements IWeChatLoginService {

//    private final static String appId = "wxcd463ea5a1baa215";
//    private final static String wxAppSecret = "f6bb06c1c7dd084a9fe8cdad91d8fdba";

    // 鼎睿游泳
    private final static String appId = "wxd7da95c397058d5c";
    private final static String wxAppSecret = "08f709ccb9bfcb3a0575f6ee116a59f0";

    private final static String code2sessionUrl = "https://api.weixin.qq.com/sns/jscode2session";

    @Resource
    private IWxUserService wxUserService;

    @Resource
    private ISysUserService sysUserService;

    @Override
    public WxCodeVo getWxCode(String wxAppId, String code) {
        // 授权（必填）
        String grant_type = "authorization_code";
        // 向微信服务器 使用登录凭证 code 获取 session_key 和 openid
        // 请求参数
        String params = "appid=" + wxAppId + "&secret=" + wxAppSecret + "&js_code=" + code + "&grant_type=" + grant_type;
        // 发送请求
        String sr = HttpUtils.sendGet(code2sessionUrl, params);
        // 解析相应内容（转换成json对象）
        JSONObject json = JSONObject.parseObject(sr);
        // 获取会话密钥（session_key）
        String session_key = json.getString("session_key");
        // 用户的唯一标识（openid）
        String openid = json.getString("openid");
        // unionId
        String unionId = json.getString("unionid");

        WxCodeVo wxCodeVo = new WxCodeVo();
        wxCodeVo.setOpenid(openid);
        wxCodeVo.setSessionKey(session_key);
        wxCodeVo.setUnionId(unionId);

        WxUserVo wxUserVo = wxUserService.selectWxUserByOpenId(openid);
        if (null != wxUserVo && null != wxUserVo.getPhone()) {
            wxCodeVo.setHasPhone(true);
        } else {
            wxCodeVo.setHasPhone(false);
        }
        return wxCodeVo;
    }

    @Override
    @Transactional
    public WxLoginVo wxLogin(String phone, String openid, String unionId, String wxAppId) {

        // 1.判断是否是新用户
        WxUserVo wxUserVo = wxUserService.selectWxUserByOpenId(openid);
        if (null == wxUserVo) {

            /** 用户表 sysUser*/
            SysUser sysUser = sysUserService.selectUniqueUserByPhone(phone);
            if (null == sysUser) {
                sysUser = new SysUser();
                sysUser.setUserName(phone);
                sysUser.setPassword(phone);
                sysUser.setNickName("用户" + phone);
                sysUser.setPhonenumber(phone);
                sysUser.setSex("2");
                sysUser.setStatus("0");
                sysUser.setRemark("来自用户端微信小程序登录");
                sysUserService.insertWxUser(sysUser);
            }
            /** 客户信息表 wxShopUser*/
            WxUserDto wxUserDto = new WxUserDto();
            wxUserDto.setUserId(sysUser.getUserId());
            wxUserDto.setUnionId(unionId);
            wxUserDto.setOpenId(openid);
            wxUserDto.setPhone(phone);
            if (StringUtils.isNotEmpty(sysUser.getSex())) {
                try {
                    wxUserDto.setSex(Integer.parseInt(sysUser.getSex()));
                } catch (Exception e) {
                    e.printStackTrace();
                    wxUserDto.setSex(2);
                }
            }
            wxUserDto.setNickName(sysUser.getNickName());
            wxUserDto.setCreateTime(DateUtils.getNowDate());
            wxUserService.insertWxUser(wxUserDto);

            /** 登录信息*/
            WxLoginVo wxLoginVo = new WxLoginVo();
            wxLoginVo.setUnionId(unionId);
            wxLoginVo.setOpenid(openid);
            wxLoginVo.setUserId(sysUser.getUserId());
            wxLoginVo.setWxUserId(wxUserDto.getId());

            wxLoginVo.setPhone(phone);
            wxLoginVo.setNickName(sysUser.getNickName());
            if (StringUtils.isNotEmpty(sysUser.getSex())) {
                try {
                    wxLoginVo.setSex(Integer.parseInt(sysUser.getSex()));
                } catch (Exception e) {
                    e.printStackTrace();
                    wxLoginVo.setSex(2);
                }
            }
            wxLoginVo.setSysUser(sysUser);
            wxLoginVo.setWxAppId(wxAppId);
            return wxLoginVo;
        } else {
            SysUser sysUser = sysUserService.selectUserById(wxUserVo.getUserId());
            // sysUser
            if (null == sysUser) {
                sysUser = new SysUser();
                sysUser.setUserName(wxUserVo.getPhone());
                sysUser.setPassword(wxUserVo.getPhone());
                sysUser.setNickName(wxUserVo.getNickName());
                sysUser.setPhonenumber(wxUserVo.getPhone());
                sysUser.setSex(wxUserVo.getSex() + "");
                sysUser.setStatus("0");
                sysUser.setRemark(wxUserVo.getRemark());
                sysUserService.insertWxUser(sysUser);
            }

            /** 登录信息*/
            WxLoginVo wxLoginVo = new WxLoginVo();
            wxLoginVo.setUnionId(unionId);
            wxLoginVo.setOpenid(openid);
            wxLoginVo.setUserId(sysUser.getUserId());
            wxLoginVo.setWxUserId(wxUserVo.getId());

            wxLoginVo.setPhone(phone);
            wxLoginVo.setNickName(sysUser.getNickName());
            if (StringUtils.isNotEmpty(sysUser.getSex())) {
                try {
                    wxLoginVo.setSex(Integer.parseInt(sysUser.getSex()));
                } catch (Exception e) {
                    e.printStackTrace();
                    wxLoginVo.setSex(2);
                }
            }
            wxLoginVo.setSysUser(sysUser);
            wxLoginVo.setWxAppId(wxAppId);
            return wxLoginVo;
        }
    }


    @Override
    public String gerPhoneNumber(WxLoginDto wxLoginDto) {
        String sSrc= wxLoginDto.getEncryptedData();
        String encodingFormat="utf-8";
        String sKey= wxLoginDto.getSessionKey();
        String ivParameter= wxLoginDto.getIv();
        String openid = wxLoginDto.getOpenid();

        WxUserVo wxUserVo = wxUserService.selectWxUserByOpenId(openid);
        if (null != wxUserVo && StringUtils.isNotEmpty(wxUserVo.getPhone())) {
            return wxUserVo.getPhone();
        }

        try {
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] raw = decoder.decodeBuffer(sKey);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            IvParameterSpec iv = new IvParameterSpec(decoder.decodeBuffer(ivParameter));
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] myendicod = decoder.decodeBuffer(sSrc);
            byte[] original = cipher.doFinal(myendicod);
            String decryptS5String = new String(original, encodingFormat);
            JSONObject jsonObject = JSONObject.parseObject(decryptS5String);
            String phoneNumber = jsonObject.getString("phoneNumber");
            return phoneNumber;
        } catch (Exception ex) {
            throw new BaseException(ex.getMessage());
        }
    }

    @Override
    public String gerPhoneNumber2(WxLoginDto wxLoginDto) {
        String openid = wxLoginDto.getOpenid();

        WxUserVo wxUserVo = wxUserService.selectWxUserByOpenId(openid);
        if (null != wxUserVo && StringUtils.isNotEmpty(wxUserVo.getPhone())) {
            return wxUserVo.getPhone();
        }

        String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token";
        String params = "grant_type=client_credential&appid=" + appId + "&secret=" + wxAppSecret;
        String sr = HttpUtils.sendGet(tokenUrl, params);
        JSONObject json = JSONObject.parseObject(sr);
        String accessToken = json.getString("access_token");


        //通过token和code来获取用户手机号
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;

        JSONObject body = new JSONObject();
        body.put("code", wxLoginDto.getCode());

        //封装请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity<Map<String, String>> httpEntity = new HttpEntity(body, headers);
        //通过RestTemplate发送请求，获取到用户手机号码
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, httpEntity, JSONObject.class);
        System.out.println("resp{}=" + response.getBody());
        String errmsg = response.getBody().getString("errmsg");
        if (errmsg.equals("ok")) {
            JSONObject phoneInfoJson = response.getBody().getJSONObject("phone_info");
            return phoneInfoJson.getString("phoneNumber");
        } else {
            throw new ServiceException(errmsg);
        }
    }
}
